在 JavaScript 裡還有一個概念稱為「Hoisting ( 提升 )」,底下先執行一段範例:
console.log(a)
// ReferenceError: a is not defined
當還沒有宣告變數的時候,JavaScript 也不會知道你要他執行什麼,於是當然會拋出錯誤;那麼如果我們改成寫這樣:
console.log(a) // undefined
var a
我們會發現他不是拋出錯誤,而是給了一個 undefined
,而實際上這樣的結果,我們就稱他為「Hoisting ( 提升 )」。但現在我們會很納悶,JavaScript 不是有所謂的運行順序嗎?照上面這個範例來看,明明不是先宣告變數,卻仍然會回傳值?
剛剛說這種情況就是所謂的「Hoisting ( 提升 )」,而「Hoisting ( 提升 )」的概念主要是在說變數、函式在宣告期間就會先建立一個記憶體空間,而這個記憶體空間就是全域記憶體( Global Memory ) 或稱記憶體堆積(Heap),等到實際運行時再將值放入到這個記憶體空間內,因此我們可以理解到為什麼上面這個範例會回傳 undefined
。
另外有一點要注意的是,只有變數的宣告會提升,賦值不會。以下面這個範例為例:
console.log(a) // undefined
var a = 5
可以直接把他拆開來看:
var a
console.log(a) // undefined
a = 5
分成兩個階段,第一階段宣告變數 var a
的時候被提升了,第二階段 a = 5
賦值則不會被提升。
let
與 const
是 ES6 之後新產生的兩個宣告變數的方法,那麼他會不會也有提升的行為呢,來看一下底下的範例:
console.log(a) // ReferenceError: a is not defined
let a
上面的範例我們會以為 let
與 const
沒有提升行為,但其實是有的,只是提升後的行為與 var
不太一樣:
var a = 10
function test(){
console.log(a)
let a
}
test()
這個範例的意思是說,假如 let
與 const
沒有提升行為,那輸出應該會是 10,但最後執行的結果是 ReferenceError: a is not defined
,因此可以斷定 let
與 const
也有提升行為。
參考資料:
JS 原力覺醒 Day06 - 提升 Hoisting
我知道你懂 hoisting,可是你了解到多深?